# -*- coding: utf-8 -*-
"""
Created on Sat Jun 25 09:03:21 2022
http://guba.eastmoney.com/list,000002,3,f.html
@author: 29165
"""
import os.path
import re
import requests
from bs4 import BeautifulSoup
import time
import pandas as pd
def get_stkcd(file,column_name='stkcd'):
    """ file:       str     文件路径
        stkcds:     list    全部股票代码
        column_name:str     股票代码对应的列名,默认为stkcd
    """
    data=pd.read_excel(file)
    #print(data.head(5))
    stkcds=list(data[column_name])
    index=0
    for stkcd in stkcds:
        stkcds[index]=str(stkcd).zfill(6)
        index+=1
    #(stkcds)
    return stkcds
def select_IPPool():
    """准备IP池"""
    pass
def cal_sumpages(text):
    """ 计算个股的公告总数和总页数,
        返回值：
            sumpages:   int     页数总和
            messages:   int     公告总数
        text： str  获取的html文本
        """
    if text=="未能爬取到网页":
        return text
    else:
        try:
            pattern=text.split("|")
            messages=int(pattern[1])
            show_message=int(pattern[2])
            if messages%show_message!=0:
                sumpages=messages//show_message+1
            else:
                sumpages=messages//show_message
            print(text,sumpages)
            return [sumpages,messages]
        except:
            return ["页数计算错误"]*2
def combine_url(url1,url2,url3,stkcd,mode,page=''):
    """得到对应股票代码的网址
        url1,url2,url3:网页地址中固定的部分
        stkcd:          对应的股票代码
        mode:
                page:   获取最大页数的模式，此模式下只需填充股票代码
                content：获取每页内容的模式，此模式下需要填充页码（page）和股票代码
        """
    if mode=="page":
        url = url1 + str(stkcd) + url2 + url3
    elif mode=="content":
        url=url1+str(stkcd)+url2+"_{}".format(str(page))+url3
    return url
def get_web(url:str):
    """格式化的request和解析"""
    r = requests.get(url)
    r.encoding='utf-8'
    html = r.text
    soup = BeautifulSoup(html, 'html.parser')
    return soup,r.status_code
def get_status_code(url:str):
    """
    返回请求状态
    :param url:
    :return:
    """
    r = requests.get(url)
    return int(r.status_code)
def get_sumpage(url):
    """
    获取总页数
    :param url:
    :return:
    """
    pagenum=[]
    try:
        soup,_=get_web(url)
        test=soup.find('span',attrs={'class':'pagernums'})
        #print(test['data-pager'])
        return cal_sumpages(test['data-pager'])
    except:
        return "未能爬取到网页"
def get_items(url,soup):
    """获取每页公告的 标题、类型和公告日期信息
     <div class="articleh normal_post">
     pan class="l9 a9"
     """
    if soup=='':
        soup,status_code=get_web(url=url)
    else:
        status_code=200
    #print(soup)
    items=soup.find_all('div',attrs={'class':'articleh normal_post'})
    titles=[item.find('a')['title'] for item in items]
    links=[item.find('a')['href'] for item in items]
    types=[item.find('span',attrs={'class':'l9 a9'}).string for item in items]
    dates=[item.find('span',attrs={'class':'l5 a5'}).string for item in items]
    return [titles,links,types,dates],status_code
def cal_startyear_endyear(items):
    """获取每一页的起止年份
        items:  list    get_items()函数的返回值
        返回值：
            startYear:  str     本页公告起始年份
            endYear:    str     本页公告截止年份
        """
    dates=items[-1]
    #print(dates)
    if dates!=[]:
        startdate,enddate=dates[-1],dates[0]
        startYear=startdate[0:4]
        endYear=enddate[0:4]
        return [startYear,endYear]
    else:
        return ['额外空页','额外空页']
def save_items(stkcd,items,page,save_path='G:\企业公告'):
    """
    保存爬取的标题、公告类型、公告日期、全文链接
    :param stkcd: 单个股票代码
    :param items: get_items()函数的返回值
    :param page: 对应的页码
    :param save_path: 保存数据的最上层路径
    :return: 无返回，至此保存至一个完整的文件
    """
    years=cal_startyear_endyear(items)
    #print(items[3])
    length=len(items[0])
    stkcds=[stkcd]*length
    titles=items[0]
    links=items[1]
    types=items[2]
    dates=items[3]
    data=pd.DataFrame([stkcds,titles,links,types,dates])
    data=data.T
    #print(data.head())
    data.columns=['stkcd','title','link','公告类型','enddate']
    if not os.path.exists(save_path+'\\'+'{}'.format(stkcd)):
        os.makedirs(save_path+'\\'+'{}'.format(stkcd))
    data.to_csv(save_path+'\\'+'{}'.format(stkcd)+'\\'+'P{}_{}_{}.csv'.format(page,years[0],years[1]),encoding='utf-8')
def get_stkcd_pages(file="test2.xlsx",stkcd_name='stkcd',page_name="总页数"):
    """
    根据operate1保存的文件，生成（股票代码，最大页数）的迭代器
    :param file: 股票代码和最大页数的来源文件，路径为operate1的保存路径
    :param stkcd_name:文件中股票代码对应的列名
    :param page_name:文件中最大页数对应的列名
    :return:（股票代码，最大页数）迭代器
    """
    data=pd.read_excel(file)
    stkcds=list(data[stkcd_name])
    page_num=list(data[page_name])
    print(stkcds)
    print(page_num)
    return stkcds,page_num,len(stkcds)
def operate1(url1,url2,url3,file):
    """
    用于生成页数，总公告数的执行程序，只需要操作一次
    :param url1:固定格式url第一段
    :param url2:固定格式url第二段
    :param url3:固定格式url第三段
    :param file:保存包含总页数的文件名（包含路径）
    :return:无返回，此为保存执行程序
    """
    stkcds = get_stkcd(file)
    urls=[combine_url(url1,url2,url3,stkcd) for stkcd in stkcds]
    sumpages=[get_sumpage(url)[0] for url in urls]
    sumitems=[get_sumpage(url)[1] for url in urls]
    data=pd.DataFrame([stkcds,urls,sumitems,sumpages])
    data=data.T
    try:
        data.columns=['stkcd','url','总公告数','总页数']
        data.to_excel('test2.xlsx')
    except:
        data.to_excel('test2.xlsx')
def operate2(vars,url1,url2,url3,mode="content"):
    """
    保存获取的基本信息
    :param vars: iterable object    存储（股票代码，最大页数）的迭代器
    :param url1:固定格式url第一段
    :param url2:固定格式url第二段
    :param url3:固定格式url第三段
    :param mode: url拼接的方式，此处为加入股票代码和页码两个参数的具体模式，具体取值为‘content’
    :return: 无返回，结果保存至文件
    """
    while True:
        try:
            var=next(vars)
            pages=iter(list(range(1,int(var[1])+1)))
            stkcd=str(var[0]).zfill(6)
            while True:
                try:
                    page=str(next(pages))
                    #print(page)
                    url=combine_url(url1, url2, url3, stkcd, mode, page)
                    #print(url)
                    save_items(stkcd,url,page)
                    print('股票{}的第{}页已获取，总共{}页'.format(stkcd,page,pages))
                    time.sleep(0.1)
                except StopIteration:
                    break
        except StopIteration:
            break




def main():
    st = time.time()
    file="全部A股公司股票代码.xls"
    url1='http://guba.eastmoney.com/list,'
    url2=',3,f'
    url3='.html'
    stkcds,page_nums,indexs= get_stkcd_pages()
    stkcds=iter(stkcds)
    total_num=indexs
    indexs=iter(list(range(indexs)))
    page_nums=iter(page_nums)

    while True:
        try:
            stkcd=next(stkcds)
            index=next(indexs)
            stkcd = str(stkcd).zfill(6)
            page_num=next(page_nums)
            pages = iter(list(range(1, page_num + 1)))
        except StopIteration:
            break
            print('已爬取完所有信息')
        while True:
            try:
                page = next(pages)
                print(page)
            except StopIteration:
                print('股票{}已获取完毕，总共{}页'.format(stkcd, page_num))
                time.sleep(0.1)
                break
            url = combine_url(url1, url2, url3, stkcd, mode='content', page=page)
            items,status_code = get_items(url,soup='')
            if status_code !=200:
                print('遭遇反爬措施')
                items,status_code = get_items(url,soup='')
                while status_code!=200:
                    time.sleep(3600)
                    items,status_code = get_items(url,soup='')
                    print(status_code)
            time.sleep(0.1)
            save_items(stkcd, items, page)



    #save_pagenum_links(url1,url2,url3,file)


main()



